﻿using System;

namespace AngularJS
{
    public class Scope
    {
        [ImportMember("$id")]
        public readonly int Id;

        /// <summary>
        /// $apply() is used to execute an expression in angular from outside of the angular framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
        /// Because we are calling into the angular framework we need to perform proper scope life cycle of exception handling, executing watches.
        /// </summary>
        /// <param name="expr"></param>
        /// <returns></returns>        
        [ImportMember("$apply")]
        public object _Apply(string expr = null)
        {
            return null;
        }

        /// <summary>
        /// $apply() is used to execute an expression in angular from outside of the angular framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
        /// Because we are calling into the angular framework we need to perform proper scope life cycle of exception handling, executing watches.
        /// </summary>
        /// <param name="func"></param>
        /// <returns></returns>
        [ImportMember("$apply")]
        public object _Apply(Action<Scope> func)
        {
            return null;
        }

        /// <summary>
        /// Dispatches an event name downwards to all child scopes (and their children) notifying the registered ng.$rootScope.Scope#methods_$on listeners.
        /// The event life cycle starts at the scope on which $broadcast was called. All listeners listening for name event on this scope get notified. Afterwards, the event propagates to all direct and indirect scopes of the current scope and calls all registered listeners along the way. The event cannot be canceled.
        /// Any exception emitted from the listeners will be passed onto the $exceptionHandler service.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="args"></param>
        [ImportMember("$broadcast")]
        public AngularEvent _Broadcast(string name, params object[] args)
        {
            return null;
        }

        /// <summary>
        /// Removes the current scope (and all of its children) from the parent scope. Removal implies that calls to $digest() will no longer propagate to the current scope and its children. Removal also implies that the current scope is eligible for garbage collection.
        /// The $destroy() is usually used by directives such as ngRepeat for managing the unrolling of the loop.
        /// Just before a scope is destroyed, a $destroy event is broadcasted on this scope. Application code can register a $destroy event handler that will give it a chance to perform any necessary cleanup.
        /// </summary>
        [ImportMember("$destroy")]
        public void _Destroy()
        {
        }

        /// <summary>
        /// Processes all of the watchers of the current scope and its children. Because a watcher's listener can change the model, the $digest() keeps calling the watchers until no more listeners are firing. This means that it is possible to get into an infinite loop. This function will throw 'Maximum iteration limit exceeded.' if the number of iterations exceeds 10.
        /// Usually, you don't call $digest() directly in controllers or in directives. Instead, you should call $apply() (typically from within a directives), which will force a $digest().
        /// If you want to be notified whenever $digest() is called, you can register a watchExpression function with $watch() with no listener.
        /// </summary>
        [ImportMember("$digest")]
        public void _Digest()
        {
        }

        /// <summary>
        /// Dispatches an event name upwards through the scope hierarchy notifying the registered ng.$rootScope.Scope#methods_$on listeners.
        /// The event life cycle starts at the scope on which $emit was called. All listeners listening for name event on this scope get notified. Afterwards, the event traverses upwards toward the root scope and calls all registered listeners along the way. The event will stop propagating if one of the listeners cancels it.
        /// Any exception emitted from the listeners will be passed onto the $exceptionHandler service.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="args"></param>
        [ImportMember("$emit")]
        public AngularEvent _Emit(string name, params object[] args)
        {
            return null;
        }

        /// <summary>
        /// Executes the expression on the current scope and returns the result. Any exceptions in the expression are propagated (uncaught). This is useful when evaluating Angular expressions.
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="locals">Local variables object, useful for overriding values in scope.</param>
        /// <returns></returns>
        [ImportMember("$eval")]
        public object _Eval(string expression, object locals = null)
        {
            return null;
        }

        /// <summary>
        /// Executes the expression on the current scope and returns the result. Any exceptions in the expression are propagated (uncaught). This is useful when evaluating Angular expressions.
        /// </summary>
        /// <param name="func"></param>
        /// <param name="locals">Local variables object, useful for overriding values in scope.</param>
        /// <returns></returns>
        [ImportMember("$eval")]
        public object _Eval(Func<object, Scope> func, object locals = null)
        {
            return null;
        }

        /// <summary>
        /// Executes the expression on the current scope at a later point in time.
        /// The $evalAsync makes no guarantees as to when the expression will be executed, only that:
        /// <para>it will execute after the function that scheduled the evaluation (preferably before DOM rendering).</para>
        /// <para>at least one $digest cycle will be performed after expression execution.</para>
        /// <para>Any exceptions from the execution of the expression are forwarded to the $exceptionHandler service.</para>
        /// </summary>
        /// <param name="expression"></param>
        [ImportMember("$evalAsync")]
        public void _EvalAsync(string expression = null)
        {
        }

        /// <summary>
        /// Executes the expression on the current scope at a later point in time.
        /// The $evalAsync makes no guarantees as to when the expression will be executed, only that:
        /// <para>it will execute after the function that scheduled the evaluation (preferably before DOM rendering).</para>
        /// <para>at least one $digest cycle will be performed after expression execution.</para>
        /// <para>Any exceptions from the execution of the expression are forwarded to the $exceptionHandler service.</para>
        /// </summary>
        /// <param name="func"></param>
        [ImportMember("$evalAsync")]
        public void _EvalAsync(Func<object, Scope> func)
        {
        }


        /// <summary>
        /// Creates a new child scope.
        /// The parent scope will propagate the $digest() and $digest() events. The scope can be removed from the scope hierarchy using $destroy().
        /// $destroy() must be called on a scope when it is desired for the scope and its child scopes to be permanently detached from the parent and thus stop participating in model change detection and listener notification by invoking.
        /// </summary>
        /// <param name="isolate">If true, then the scope does not prototypically inherit from the parent scope. The scope is isolated, as it can not see parent scope properties. When creating widgets, it is useful for the widget to not accidentally read parent state.</param>
        /// <returns></returns>
        [ImportMember("$new")]
        public Scope _New(bool isolate)
        {
            return null;
        }

        /// <summary>
        /// Listens on events of a given type. See $emit for discussion of event life cycle.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="listener"></param>
        /// <returns>Returns a deregistration function for this listener.</returns>
        [ImportMember("$on")]
        public Action _On(string name, Action<AngularEvent> listener)
        {
            return null;
        }

        /// <summary>
        /// Listens on events of a given type. See $emit for discussion of event life cycle.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <param name="listener"></param>
        /// <returns>Returns a deregistration function for this listener.</returns>
        [ImportMember("$on")]
        public Action _On<T>(string name, Action<AngularEvent, T> listener)
        {
            return null;
        }

        /// <summary>
        /// Listens on events of a given type. See $emit for discussion of event life cycle.
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="name"></param>
        /// <param name="listener"></param>
        /// <returns>Returns a deregistration function for this listener.</returns>
        [ImportMember("$on")]
        public Action _On<T1, T2>(string name, Action<AngularEvent, T1, T2> listener)
        {
            return null;
        }

        /// <summary>
        /// Registers a listener callback to be executed whenever the watchExpression changes.
        /// </summary>
        /// <param name="watchExpression"></param>
        /// <param name="listener">function(newValue, oldValue, scope): called with current and previous values as parameters.</param>
        /// <param name="objectEquality">Compare object for equality rather than for reference.</param>
        /// <returns>Returns a deregistration function for this listener.</returns>
        [ImportMember("$watch")]
        public Action _Watch(string watchExpression, Action<object, object, Scope> listener, bool objectEquality)
        {
            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="func"></param>
        /// <param name="listener">function(newValue, oldValue, scope): called with current and previous values as parameters.</param>
        /// <param name="objectEquality">Compare object for equality rather than for reference.</param>
        /// <returns>Returns a deregistration function for this listener.</returns>
        [ImportMember("$watch")]
        public Action _Watch(Func<object, Scope> func, Action<object, object, Scope> listener, bool objectEquality)
        {
            return null;
        }

        /// <summary>
        /// Shallow watches the properties of an object and fires whenever any of the properties change
        /// (for arrays, this implies watching the array items; for object maps, this implies watching the properties).
        /// If a change is detected, the listener callback is fired.
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="listener">function(newCollection, oldCollection, scope)</param>
        /// <returns>Returns a de-registration function for this listener.</returns>
        [ImportMember("$watchCollection")]
        public Action _WatchCollection(string expression, Action<object, object, Scope> listener)
        {
            return null;
        }
    }
}
